#include "MyGLWidget.h"
#include <QDebug>
#include <algorithm>

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

MyGLWidget::MyGLWidget(QWidget *parent) : QOpenGLWidget(parent), m_program(nullptr) {
    m_cameraDistance = 15.0f;
    m_cameraYaw = 0.0f;
    m_cameraPitch = 15.0f;
}

MyGLWidget::~MyGLWidget() {
    makeCurrent();
    m_model.cleanup();
    doneCurrent();
}

void MyGLWidget::initializeGL() {
    initializeOpenGLFunctions();
    m_model.initialize();

    qInfo() << "OpenGL Version:" << (const char*)glGetString(GL_VERSION);
    glClearColor(0.1f, 0.15f, 0.25f, 1.0f);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_MULTISAMPLE);

    m_program = new QOpenGLShaderProgram(this);

    // --- 顶点着色器无变化 ---
    const char* vsrc =
        "#version 300 es\n"
        "layout (location = 0) in vec3 aPos;\n"
        "layout (location = 1) in vec3 aNormal;\n"
        "uniform mat4 model;\n"
        "uniform mat4 view;\n"
        "uniform mat4 projection;\n"
        "out vec3 Normal;\n"
        "out vec3 FragPos;\n"
        "void main()\n"
        "{\n"
        "   gl_Position = projection * view * model * vec4(aPos, 1.0);\n"
        "   FragPos = vec3(model * vec4(aPos, 1.0));\n"
        "   Normal = mat3(transpose(inverse(model))) * aNormal;\n"
        "}\n";
    m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vsrc);

    // --- 关键改动: 支持多光源的片段着色器 ---
    const char* fsrc =
        "#version 300 es\n"
        "precision mediump float;\n"
        "in vec3 Normal;\n"
        "in vec3 FragPos;\n"
        "out vec4 FragColor;\n"
        // --- Uniforms ---
        "uniform vec3 viewPos;\n"
        "uniform vec3 objectColor;\n"
        "uniform vec3 lightPos1; // 第1个光源位置\n"
        "uniform vec3 lightPos2; // 第2个光源位置\n"

        // --- 函数: 计算单个点光源的光照效果 ---\n"
        "vec3 CalcPointLight(vec3 lightPos, vec3 norm, vec3 fragPos, vec3 viewDir)\n"
        "{\n"
        "   // 漫反射光\n"
        "   vec3 lightDir = normalize(lightPos - fragPos);\n"
        "   float diff = max(dot(norm, lightDir), 0.0);\n"
        "   vec3 diffuse = diff * vec3(1.0, 1.0, 1.0);\n"
        "   // 镜面高光\n"
        "   float specularStrength = 0.8;\n"
        "   vec3 reflectDir = reflect(-lightDir, norm);\n"
        "   float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32.0);\n"
        "   vec3 specular = specularStrength * spec * vec3(1.0, 1.0, 1.0);\n"
        "   return (diffuse + specular);\n"
        "}\n"

        "void main()\n"
        "{\n"
        "   vec3 norm = normalize(Normal);\n"
        "   vec3 viewDir = normalize(viewPos - FragPos);\n"
        "   // 环境光 (只需计算一次)\n"
        "   float ambientStrength = 0.2;\n"
        "   vec3 ambient = ambientStrength * vec3(1.0, 1.0, 1.0);\n"
        "   // 计算来自两个光源的光照并叠加\n"
        "   vec3 result = CalcPointLight(lightPos1, norm, FragPos, viewDir) + \n"
        "                 CalcPointLight(lightPos2, norm, FragPos, viewDir);\n"
        "   // 最终颜色 = (环境光 + 总光照) * 物体基色\n"
        "   vec3 finalColor = (ambient + result) * objectColor;\n"
        "   FragColor = vec4(finalColor, 1.0);\n"
        "}\n";
    m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fsrc);
    m_program->link();

    // m_model.loadFromFile("low-poly_tesla_cybertruck.glb");
    // m_model.loadFromFile("spacex_starship.glb");
    // m_model.loadFromFile("mq_9_reaper_no_decals.glb");
    m_model.loadFromFile("ukrainian_bayraktar_tb2.glb");
}

void MyGLWidget::paintGL() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    m_program->bind();

    QMatrix4x4 modelMatrix;
    modelMatrix.setToIdentity();
    modelMatrix.rotate(-90, 1.0f, 0.0f, 0.0f);

    QMatrix4x4 viewMatrix;
    QVector3D cameraPos;
    cameraPos.setX(m_cameraDistance * std::cos(m_cameraPitch * M_PI/180.0) * std::sin(m_cameraYaw * M_PI/180.0));
    cameraPos.setY(m_cameraDistance * std::sin(m_cameraPitch * M_PI/180.0));
    cameraPos.setZ(m_cameraDistance * std::cos(m_cameraPitch * M_PI/180.0) * std::cos(m_cameraYaw * M_PI/180.0));
    viewMatrix.lookAt(cameraPos, QVector3D(0.0f, 0.0f, 0.0f), QVector3D(0.0f, 1.0f, 0.0f));

    m_program->setUniformValue("projection", m_projection);
    m_program->setUniformValue("view", viewMatrix);
    m_program->setUniformValue("model", modelMatrix);
    m_program->setUniformValue("objectColor", QVector3D(0.75f, 0.75f, 0.75f));
    m_program->setUniformValue("viewPos", cameraPos);

    // --- 关键改动: 传递两个光源的位置 ---
    // 第1个光源 (在右边)
    m_program->setUniformValue("lightPos1", QVector3D(20.0f, 30.0f, 40.0f));
    // 第2个光源 (在左边)
    m_program->setUniformValue("lightPos2", QVector3D(-20.0f, 30.0f, 40.0f));

    m_model.draw();
    m_program->release();
}

void MyGLWidget::resizeGL(int w, int h) {
    if (h == 0) h = 1;
    m_projection.setToIdentity();
    m_projection.perspective(45.0f, float(w) / float(h), 0.1f, 100.0f);
}

void MyGLWidget::wheelEvent(QWheelEvent *event) {
    int steps = event->angleDelta().y() / 120;
    m_cameraDistance -= steps * 1.0f;
    m_cameraDistance = qBound(5.0f, m_cameraDistance, 50.0f);
    update();
}

void MyGLWidget::mousePressEvent(QMouseEvent *event) {
    if (event->buttons() & Qt::LeftButton) {
        m_lastMousePos = event->pos();
    }
}

void MyGLWidget::mouseMoveEvent(QMouseEvent *event) {
    if (event->buttons() & Qt::LeftButton) {
        int dx = event->x() - m_lastMousePos.x();
        int dy = event->y() - m_lastMousePos.y();

        m_cameraYaw -= dx * 0.25f;
        m_cameraPitch += dy * 0.25f;

        m_cameraPitch = qBound(-89.0f, m_cameraPitch, 89.0f);

        m_lastMousePos = event->pos();
        update();
    }
}
